# index.html CaoBooru
# post.html Post - CaoBooru
Post image
# style.css :root{ --bg:#000; --panel:#0f0f0f; --muted:#bfc7d1; --accent:#8fd7ff; } *{box-sizing:border-box} html,body{height:100%} body{ margin:0; background:var(--bg); color:var(--muted); font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; } .topbar{ display:flex; align-items:center; gap:12px; background:linear-gradient(180deg,#0b0b0b, #0f0f0f); padding:10px 16px; border-bottom:1px solid #222; } .logo{width:36px;height:36px;object-fit:cover;border-radius:4px} .nav-links{margin-left:8px;display:flex;gap:18px} .nav-links a{color:var(--muted);text-decoration:none;font-weight:600} .layout{display:grid;grid-template-columns:260px 1fr;min-height:calc(100vh - 56px)} .sidebar{background:var(--panel);padding:16px;border-right:1px solid #111} .search-box input{width:100%;padding:8px;border-radius:6px;border:1px solid #222;background:#0b0b0b;color:var(--muted)} .tag-list{margin-top:14px;font-size:14px;line-height:1.6} .tag-list span{display:inline-block;padding:6px 8px;margin:4px 6px 0 0;background:#071526;color:var(--accent);border-radius:6px;cursor:pointer} .gallery{padding:18px;display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px} .thumb-link{display:block;border-radius:6px;overflow:hidden;background:#070707;border:1px solid #111} .thumb-img{width:100%;height:220px;object-fit:cover;display:block} .post-view{padding:20px} .post-inner{max-width:1100px;margin:0 auto} .post-image{width:100%;height:auto;border-radius:6px;display:block} .post-tags{margin-top:10px} .post-tags span{display:inline-block;margin-right:8px;padding:6px 8px;background:#071526;color:var(--accent);border-radius:6px} /* mobile */ @media (max-width:900px){ .layout{grid-template-columns:1fr} .sidebar{order:2} } # posts.json { "posts": [ { "id": "p001", "file": "img/sample1.png", "tags": ["general","character","copyright"] }, { "id": "p002", "file": "img/sample2.png", "tags": ["general","mothgirl","copyright"] } ] } # gallery.js // Minimal booru-like static frontend for Neocities let posts = []; let allTags = []; async function loadPosts(){ try{ const res = await fetch('posts.json',{cache:'no-store'}); const data = await res.json(); posts = data.posts || []; buildTagIndex(); renderTags(); renderGallery(posts); initSearchAutocomplete(); // if URL has ?tag=foo prefilter const q = new URLSearchParams(location.search).get('tag'); if(q) filterByTag(q); }catch(e){ console.error('Failed to load posts.json',e); } } function buildTagIndex(){ const set = new Set(); posts.forEach(p=>p.tags.forEach(t=>set.add(t))); allTags = Array.from(set).sort((a,b)=>a.localeCompare(b)); } function renderTags(){ const el = document.getElementById('tagList'); if(!el) return; el.innerHTML = allTags.map(t=>`${t}`).join(''); } function renderGallery(list){ const gal = document.getElementById('gallery'); if(!gal) return; gal.innerHTML = ''; list.forEach(p=>{ const a = document.createElement('a'); a.className = 'thumb-link'; a.href = `post.html?id=${encodeURIComponent(p.id)}`; const img = document.createElement('img'); img.className='thumb-img'; img.src = p.file; img.alt = p.tags.join(', '); a.appendChild(img); gal.appendChild(a); }); } function filterByTag(tag){ const filtered = posts.filter(p=>p.tags.includes(tag)); renderGallery(filtered); const input = document.getElementById('searchInput'); if(input) input.value = tag; } // simple search by substring of tags function initSearchAutocomplete(){ const input = document.getElementById('searchInput'); if(!input) return; let currentList = []; const ac = document.createElement('div'); ac.className='ac-box'; ac.style.position='absolute'; ac.style.background='#0b0b0b'; ac.style.border='1px solid #222'; ac.style.padding='6px'; ac.style.display='none'; ac.style.zIndex='2000'; input.parentNode.appendChild(ac); input.addEventListener('input',e=>{ const q = e.target.value.trim().toLowerCase(); if(!q){ ac.style.display='none'; renderGallery(posts); return; } const matches = allTags.filter(t=>t.includes(q)); currentList = matches.slice(0,12); ac.innerHTML = currentList.map(t=>`
${t}
`).join(''); ac.style.display = currentList.length? 'block':'none'; positionAc(input,ac); // live filter const filtered = posts.filter(p=>p.tags.some(t=>t.includes(q))); renderGallery(filtered); }); ac.addEventListener('click', e=>{ const t = e.target.closest('.ac-item'); if(!t) return; const tag = t.getAttribute('data-tag'); filterByTag(tag); ac.style.display='none'; }); document.addEventListener('click',e=>{ if(!ac.contains(e.target) && e.target!==input) ac.style.display='none'; }); } function positionAc(input,ac){ const r = input.getBoundingClientRect(); ac.style.left = (r.left + window.scrollX) + 'px'; ac.style.top = (r.bottom + window.scrollY + 6) + 'px'; ac.style.minWidth = r.width + 'px'; } loadPosts(); # post.js let postsData = []; async function loadPost(){ try{ const res = await fetch('posts.json',{cache:'no-store'}); const data = await res.json(); postsData = data.posts || []; renderTagsSidebar(); const id = new URLSearchParams(location.search).get('id'); const post = postsData.find(p=>p.id===id); if(!post){ document.getElementById('postView').innerHTML = '

Post not found.

'; return; } document.getElementById('postImage').src = post.file; document.getElementById('postImage').alt = post.tags.join(', '); document.getElementById('postTags').innerHTML = post.tags.map(t=>`${t}`).join(''); }catch(e){ console.error(e); } } function renderTagsSidebar(){ const set = new Set(); postsData.forEach(p=>p.tags.forEach(t=>set.add(t))); const arr = Array.from(set).sort((a,b)=>a.localeCompare(b)); const el = document.getElementById('tagList'); if(!el) return; el.innerHTML = arr.map(t=>`${t}`).join(''); } loadPost();